home *** CD-ROM | disk | FTP | other *** search
- /*********************************************************************
- File : UnixFiles.h - Macintosh implementation of some things
- useful for handling UN*X files and such.
- Author : Matthias Neeracher <neeri@iis.ethz.ch>
- Started : 28May91 Language : MPW C
- 28May91 MN Created
- 28May91 MN isatty()
- 09Dec91 MN Radical overhaul
- 12Dec91 MN FSp2RelPath
- Last : 12Dec91
-
- Copyright (c) 1991, 1992 Matthias Neeracher
-
- You may distribute under the terms of either the GNU General Public
- License or the Artistic License, as specified in the README file.
-
- *********************************************************************/
-
- /* We need glue for Gestalt, but not for the rest of the stuff */
- #include <GestaltEqu.h>
-
- #define SystemSevenOrLater 1
- #include "UnixFiles.h"
-
- #include <Errors.h>
- #include <Memory.h>
- #include <string.h>
- #include <ioctl.h>
- #include <fcntl.h>
- #include <errno.h>
-
- typedef enum {
- dontKnow,
- canRun,
- cantRun
- } featureCheck;
-
- /* Convert a working directory & file name into a FSSpec. */
- OSErr WD2FSSpec(short wd, Str63 name, FSSpec * desc)
- {
- OSErr err;
- WDPBRec wdPB;
-
- wdPB.ioNamePtr = nil;
- wdPB.ioVRefNum = wd;
- wdPB.ioWDIndex = 0;
- wdPB.ioWDProcID = 0;
-
- /* Change the Working Directory number in vRefnum into a real vRefnum */
- /* and DirID. The real vRefnum is returned in ioVRefnum, and the real */
- /* DirID is returned in ioWDDirID. */
-
- if (err = PBGetWDInfoSync(&wdPB))
- return err;
-
- desc->vRefNum = wdPB.ioWDVRefNum;
- desc->parID = wdPB.ioWDDirID;
- memcpy(desc->name, name, *name+1);
-
- return noErr;
- }
-
- #define maxPathLen 512
-
- static char fullPath[maxPathLen];
-
- /* Convert an FSSpec into a full pathname. The pathname is accumulated on the
- high end of path to avoid excessive copying.
- */
-
- char * FSp2FullPath(const FSSpec * desc)
- {
- CInfoPBRec block;
- char * curPath;
-
- /* Special case: a volume was specified */
- if (desc->parID == fsRtParID) {
- memcpy(fullPath, desc->name+1, *desc->name);
- curPath = fullPath+*desc->name;
- curPath[0] = ':';
- curPath[1] = 0;
-
- return fullPath;
- }
-
- fullPath[maxPathLen-1] = 0;
- curPath = fullPath+maxPathLen-*desc->name-1;
-
- memcpy(curPath, desc->name+1, *desc->name);
-
- block.dirInfo.ioNamePtr = (StringPtr) fullPath;
- block.dirInfo.ioDrParID = desc->parID;
-
- do {
- block.dirInfo.ioVRefNum = desc->vRefNum;
- block.dirInfo.ioFDirIndex = -1;
- block.dirInfo.ioDrDirID = block.dirInfo.ioDrParID;
-
- PBGetCatInfoSync(&block);
- *--curPath = ':';
- curPath -= *fullPath;
- memmove(curPath, fullPath+1, *fullPath);
- } while (block.dirInfo.ioDrDirID != fsRtDirID);
-
- return curPath;
- }
-
- char * FSp2RelPath(const FSSpec * desc)
- {
- short curVRef;
- long curDirID;
- CInfoPBRec block;
- char * curPath;
-
- {
- WDPBRec vol;
-
- vol.ioNamePtr = (StringPtr)fullPath;
-
- PBHGetVolSync(&vol);
-
- curVRef = vol.ioWDVRefNum;
- curDirID = vol.ioWDDirID;
- }
-
- /* Special case: a volume was specified */
- if (desc->parID == fsRtParID) {
- if (desc->vRefNum == curVRef && curDirID == fsRtDirID)
- curPath = fullPath;
- else {
- memcpy(fullPath, desc->name+1, *desc->name);
- curPath = fullPath+*desc->name;
- }
-
- curPath[0] = ':';
- curPath[1] = 0;
-
- return fullPath;
- }
-
- block.dirInfo.ioNamePtr = (StringPtr)fullPath;
- block.dirInfo.ioVRefNum = curVRef;
- block.dirInfo.ioFDirIndex = -1;
- block.dirInfo.ioDrDirID = curDirID;
-
- PBGetCatInfoSync(&block);
-
- if (curVRef == desc->vRefNum
- && block.dirInfo.ioDrParID == desc->parID
- && !memcmp (fullPath, desc->name, *fullPath+1)
- ) {
- fullPath[0] = ':';
- fullPath[1] = 0;
-
- return fullPath;
- }
-
- fullPath[maxPathLen-1] = 0;
- curPath = fullPath+maxPathLen-*desc->name-1;
-
- memcpy(curPath, desc->name+1, *desc->name);
-
- block.dirInfo.ioNamePtr = (StringPtr) fullPath;
- block.dirInfo.ioDrParID = desc->parID;
-
- do {
- *--curPath = ':';
-
- /* Test fur current directory */
- if (curVRef == desc->vRefNum && curDirID == block.dirInfo.ioDrParID)
- return strchr(curPath+1, ':') ? curPath : curPath+1;
-
- block.dirInfo.ioVRefNum = desc->vRefNum;
- block.dirInfo.ioFDirIndex = -1;
- block.dirInfo.ioDrDirID = block.dirInfo.ioDrParID;
-
- PBGetCatInfoSync(&block);
- curPath -= *fullPath;
- memmove(curPath, fullPath+1, *fullPath);
- } while (block.dirInfo.ioDrDirID != fsRtDirID);
-
- return curPath;
- }
-
-
- /* Call GetCatInfo for file system object. */
- OSErr FSpCatInfo(const FSSpec * desc, CInfoPBRec * info)
- {
- info->dirInfo.ioVRefNum = desc->vRefNum;
- info->dirInfo.ioDrDirID = desc->parID;
- info->dirInfo.ioNamePtr = desc->name;
- info->dirInfo.ioFDirIndex = 0;
-
- return PBGetCatInfoSync(info);
- }
-
- /* Is Object a file ? */
- Boolean IsFile(const CInfoPBRec * info)
- {
- return !(info->dirInfo.ioFlAttrib & 0x10);
- }
-
- /* Return FSSpec of (vRefNum, parID) */
- OSErr FSpUp(FSSpec * desc)
- {
- OSErr err;
- CInfoPBRec cb;
-
- if (desc->parID == fsRtParID)
- return noErr;
-
- cb.dirInfo.ioVRefNum = desc->vRefNum;
- cb.dirInfo.ioDrDirID = desc->parID;
- cb.dirInfo.ioNamePtr = desc->name;
- cb.dirInfo.ioFDirIndex = -1;
-
- if (err = PBGetCatInfoSync(&cb))
- return err;
-
- desc->parID = (desc->parID == fsRtDirID) ? fsRtParID : cb.dirInfo.ioDrParID;
-
- return noErr;
- }
-
- /* Return FSSpec of file in directory denoted by desc */
- OSErr FSpDown(FSSpec * desc, ConstStr31Param name)
- {
- OSErr err;
- CInfoPBRec cb;
-
- if (err = FSpCatInfo(desc, &cb))
- return err;
- if (IsFile(&cb))
- return bdNamErr;
-
- desc->parID = cb.dirInfo.ioDrDirID;
-
- memcpy(desc->name, name, *name+1);
-
- return noErr;
- }
-
- /* Return FSSpec of nth file in directory denoted by (vRefNum, parID) */
- OSErr FSpIndex(FSSpec * desc, short n)
- {
- CInfoPBRec cb;
-
- cb.dirInfo.ioVRefNum = desc->vRefNum;
- cb.dirInfo.ioDrDirID = desc->parID;
- cb.dirInfo.ioNamePtr = desc->name;
- cb.dirInfo.ioFDirIndex = n;
-
- return PBGetCatInfoSync(&cb);
- }
-
- /* A version of PBGetCatInfo for c strings that may be longer than 255 chars
- */
-
- static OSErr GetCatInfo(char * path, CInfoPBPtr cb)
- {
- char * nextPath;
- char * tryPath;
- OSErr err;
- StringPtr name = (StringPtr) fullPath;
-
- if (*path != ':' && (nextPath = strchr(path, ':'))) {
- ParamBlockRec vol;
-
- memcpy(name+1, path, *name = nextPath-path+1);
-
- vol.volumeParam.ioNamePtr = name;
- vol.volumeParam.ioVolIndex = -1;
-
- if (err = PBGetVInfoSync(&vol))
- return err;
-
- cb->dirInfo.ioVRefNum = vol.volumeParam.ioVRefNum;
- cb->dirInfo.ioDrDirID = fsRtDirID;
-
- path = nextPath;
- } else {
- WDPBRec vol;
-
- vol.ioNamePtr = name;
-
- if (err = PBHGetVolSync(&vol))
- return err;
-
- cb->dirInfo.ioVRefNum = vol.ioWDVRefNum;
- cb->dirInfo.ioDrDirID = vol.ioWDDirID;
- }
-
- cb->dirInfo.ioNamePtr = name;
- cb->dirInfo.ioFDirIndex = 0;
-
- /* handle very long pathnames */
-
- while (strlen(path) > 255) {
- for (nextPath = path; tryPath = strchr(nextPath, ':'); nextPath = tryPath)
- if (tryPath-nextPath > 31)
- return bdNamErr;
- else if (tryPath-path > 255)
- break;
-
- if (nextPath == path && !tryPath)
- return bdNamErr;
-
- memcpy(name+1, path, name[0] = nextPath-path);
-
- if (err = PBGetCatInfoSync(cb))
- return err;
-
- if (IsFile(cb))
- return bdNamErr;
-
- cb->dirInfo.ioFDirIndex = 0;
-
- path = nextPath+1;
- }
-
- memcpy(name+1, path, name[0] = strlen(path));
-
- if (err = PBGetCatInfoSync(cb))
- return err;
-
- if (!IsFile(cb)) {
- cb->dirInfo.ioFDirIndex = -1;
-
- return PBGetCatInfoSync(cb);
- } else {
- while (fullPath[*fullPath] == ':')
- fullPath[(*fullPath)--] = 0;
-
- if (path = strrchr(fullPath+1, ':'))
- memcpy(fullPath+1, path+1, *fullPath = path-fullPath);
-
- return noErr;
- }
- }
-
- OSErr Path2FSSpec(char * path, FSSpec * desc)
- {
- static featureCheck hasFSMakeFSSpec = dontKnow;
-
- int pathLen = strlen(path);
-
- if (hasFSMakeFSSpec == dontKnow) {
- long attr;
-
- if (!Gestalt(gestaltFSAttr, &attr) && (attr & gestaltHasFSSpecCalls))
- hasFSMakeFSSpec = canRun;
- else
- hasFSMakeFSSpec = cantRun;
- }
-
- if (hasFSMakeFSSpec == canRun && pathLen<256) {
- Str255 pathName;
-
- memcpy(pathName+1, path, pathLen);
-
- *pathName = pathLen;
-
- return FSMakeFSSpec(0, 0, pathName, desc);
- } else {
- OSErr err;
- CInfoPBRec cb;
-
- if (err = GetCatInfo(path, &cb))
- return err;
-
- desc->vRefNum = cb.hFileInfo.ioVRefNum;
- desc->parID = cb.hFileInfo.ioFlParID;
-
- memcpy(desc->name, fullPath, *fullPath+1);
- }
-
- return noErr;
- }
-
- static OSErr GetFDCatInfo(int fd, CInfoPBPtr cb)
- {
- short fRef;
- OSErr err;
- FCBPBRec fcb;
- Str255 fname;
-
- if (ioctl(fd, FIOREFNUM, (long *) &fRef) == -1)
- return fnfErr;
-
- fcb.ioNamePtr = fname;
- fcb.ioRefNum = fRef;
- fcb.ioFCBIndx = 0;
- if (err = PBGetFCBInfoSync(&fcb))
- return err;
-
- cb->hFileInfo.ioNamePtr = fname;
- cb->hFileInfo.ioDirID = fcb.ioFCBParID;
- cb->hFileInfo.ioVRefNum = fcb.ioFCBVRefNum;
- cb->hFileInfo.ioFDirIndex = 0;
-
- return PBGetCatInfoSync(cb);
- }
-
- static OSErr GetVolume(CInfoPBPtr cb, ParmBlkPtr pb)
- {
- Str63 name;
-
- pb->volumeParam.ioNamePtr = name;
- pb->volumeParam.ioVRefNum = cb->hFileInfo.ioVRefNum;
- pb->volumeParam.ioVolIndex = 0;
-
- return PBGetVInfo(pb, false);
- }
-
- static int do_stat(CInfoPBPtr cb, ParmBlkPtr pb, struct stat * buf)
- {
- buf->st_dev = pb->ioParam.ioVRefNum;
- buf->st_ino = cb->hFileInfo.ioDirID;
- buf->st_nlink = 1;
- buf->st_uid = 0;
- buf->st_gid = 0;
- buf->st_rdev = 0;
- buf->st_atime = cb->hFileInfo.ioFlMdDat;
- buf->st_mtime = cb->hFileInfo.ioFlMdDat;
- buf->st_ctime = cb->hFileInfo.ioFlCrDat;
- buf->st_blksize= pb->volumeParam.ioVAlBlkSiz;
-
- if (!IsFile(cb)) {
- buf->st_mode = S_IFDIR | 0777;
- buf->st_size = buf->st_blksize; /* Not known for directories */
- } else {
- buf->st_mode = S_IFREG | 0666;
-
- if (cb->hFileInfo.ioFlAttrib & 0x01)
- buf->st_mode&= 0222;
-
- if (cb->hFileInfo.ioFlFndrInfo.fdType == 'APPL')
- buf->st_mode|= 0111;
-
- buf->st_size = cb->hFileInfo.ioFlLgLen; /* Resource fork is ignored */
- }
-
- buf->st_blocks = (buf->st_size + buf->st_blksize - 1) / buf->st_blksize;
-
- return 0;
- }
-
- int stat(char * path, struct stat * buf)
- {
- CInfoPBRec cb;
- ParamBlockRec pb;
-
- if (GetCatInfo(path, &cb) || GetVolume(&cb, &pb)) {
- errno = ENOENT;
-
- return -1;
- } else
- return do_stat(&cb, &pb, buf);
- }
-
- /* Not yet really implemented */
-
- int lstat(char * path, struct stat * buf)
- {
- return stat(path, buf);
- }
-
- int fstat(int fd, struct stat * buf)
- {
- CInfoPBRec cb;
- ParamBlockRec pb;
-
- if (GetFDCatInfo(fd, &cb))
- if (lseek(fd, (long) 0, SEEK_CUR) != -1) {
- /* lseek() works, assume that this is a pseudo file (e.g. Dev:Null)
- (Provided by Tim Endres <time@ice.com>)
- */
- buf->st_dev = 0;
- buf->st_ino = 0;
- buf->st_mode = S_IFCHR | 0777;
- buf->st_nlink = 1;
- buf->st_uid = 0;
- buf->st_gid = 0;
- buf->st_rdev = 0;
- buf->st_size = 1;
- buf->st_atime = time(NULL);
- buf->st_mtime = time(NULL);
- buf->st_ctime = time(NULL);
- buf->st_blksize = 1;
- buf->st_blocks = 1;
-
- return 0;
- } else {
- errno = ENOENT;
-
- return -1;
- }
- else if (GetVolume(&cb, &pb)) {
- errno = ENOENT;
-
- return -1;
- } else
- return do_stat(&cb, &pb, buf);
- }
-
- int isatty(int fd)
- {
- short fRef;
-
- /* Another application of Tim Endres' idea. Neat, huh ? */
-
- return (ioctl(fd, FIOREFNUM, (long *) &fRef) == -1) &&
- (lseek(fd, (long) 0, SEEK_CUR) != -1);
- }
-
- struct dir {
- short index;
- short vol;
- long dirID;
- direct entry;
- };
-
- DIR * opendir(char * name)
- {
- DIR * d;
- CInfoPBRec direct;
-
- d = (DIR *) NewPtr(sizeof(DIR));
-
- if (!d)
- return nil;
- else if (GetCatInfo(name, &direct) || IsFile(&direct)) {
- DisposPtr((Ptr) d);
- return nil;
- }
-
- d->index = 1;
- d->vol = direct.dirInfo.ioVRefNum;
- d->dirID = direct.dirInfo.ioDrDirID;
-
- return d;
- }
-
- direct * readdir(DIR * dirp)
- {
- CInfoPBRec info;
-
- dirp->entry.d_namelen = 0;
- info.hFileInfo.ioNamePtr = (StringPtr) dirp->entry.d_name-1;
- info.hFileInfo.ioVRefNum = dirp->vol;
- info.hFileInfo.ioFDirIndex = dirp->index;
- info.hFileInfo.ioDirID = dirp->dirID;
-
- if (PBGetCatInfo(&info, false))
- return nil;
-
- dirp->entry.d_name[dirp->entry.d_namelen] = 0;
- dirp->index++;
-
- return &dirp->entry;
- }
-
- long telldir(DIR * dirp)
- {
- return dirp->index;
- }
-
- void seekdir(DIR * dirp, long loc)
- {
- dirp->index = loc;
- }
-
- void rewinddir(DIR * dirp)
- {
- dirp->index = 1;
- }
-
- void closedir(DIR * dirp)
- {
- DisposPtr((Ptr) dirp);
- }
-
- int chdir(char * path)
- {
- short vRef;
- CInfoPBRec cb;
-
- if (GetCatInfo(path, &cb) ||╩IsFile(&cb)) {
- errno = ENOENT;
-
- return -1;
- }
-
- /* HSetVol is too dangerous, create WD if necessary */
- if (cb.dirInfo.ioDrDirID != fsRtDirID)
- OpenWD(cb.dirInfo.ioVRefNum, cb.dirInfo.ioDrDirID, 'ERIK', &vRef);
- else
- vRef = cb.dirInfo.ioVRefNum;
-
- SetVol(nil, vRef);
-
- return 0;
- }
-
- int mkdir(char * path)
- {
- OSErr err;
- short vRef;
- long dirID;
- long nuDir;
- int len;
- char * dirPart;
- Str31 name;
-
- if (dirPart = strrchr(path, ':')) {
- char saveCh;
- CInfoPBRec cb;
-
- saveCh = dirPart[1];
- dirPart[1] = 0;
- err = GetCatInfo(path, &cb);
- dirPart[1] = saveCh;
-
- if (err ||╩IsFile(&cb)) {
- errno = ENOENT;
-
- return -1;
- }
-
- if ((len = strlen(dirPart+1)) > 31)
- return bdNamErr;
-
- memcpy(name+1, dirPart+1, *name = len);
-
- vRef = cb.dirInfo.ioVRefNum;
- dirID = cb.dirInfo.ioDrDirID;
- } else {
- WDPBRec vol;
-
- vol.ioNamePtr = name;
-
- if (err = PBHGetVolSync(&vol))
- return err;
-
- if ((len = strlen(path)) > 31)
- return bdNamErr;
-
- memcpy(name+1, path, *name = len);
-
- vRef = vol.ioWDVRefNum;
- dirID = vol.ioWDDirID;
- }
-
- if (err = DirCreate(vRef, dirID, name, &nuDir)) {
- switch (err) {
- case bdNamErr:
- case dirNFErr:
- default:
- errno = ENOENT;
- break;
- case dupFNErr:
- errno = EEXIST;
- break;
- case dirFulErr:
- errno = ENOSPC;
- break;
- }
-
- return -1;
- }
-
- return 0;
- }
-
- int rmdir(char * path)
- {
- OSErr err;
- CInfoPBRec cb;
-
- if (GetCatInfo(path, &cb) ||╩IsFile(&cb)) {
- errno = ENOENT;
-
- return -1;
- }
-
- if (err = HDelete(cb.dirInfo.ioVRefNum, cb.dirInfo.ioDrDirID, "")) {
- switch (err) {
- case bdNamErr:
- case dirNFErr:
- default:
- errno = ENOENT;
- break;
- case dupFNErr:
- case fBsyErr:
- errno = EEXIST;
- break;
- case dirFulErr:
- errno = ENOSPC;
- break;
- }
-
- return -1;
- }
-
- return 0;
- }
-
-